home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / cut.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  20KB  |  869 lines

  1. /*
  2.  * $Id: cut.c,v 0.91 1994/02/20 00:53:03 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  *   Purpose:
  26.  *    Cut & Paste. If C&P is done across images, the resulting
  27.  *    image will be in RGB.
  28.  *
  29.  */
  30. #if  !defined(lint) && defined(F_ID)
  31. char *id_cp = "$Id: cut.c,v 0.91 1994/02/20 00:53:03 zhao Pre-Release $";
  32. #endif
  33.  
  34. #include "bit.h"
  35. #include "extern.h"
  36. #include "dmalloc.h"
  37.  
  38. /********************* Cut buffer definations ****************/
  39. typedef struct
  40.   {
  41.       int w, h;            /* dumenion of cut */
  42.       void *buf;        /* the matrix      */
  43.       void *rasbuf;        /* the raster      */
  44.   }
  45. cpbuf_t;
  46.  
  47. /*************** Local variables ************************/
  48.  
  49. static int empty;        /* if a buffer available        */
  50. static int wd = 100, ht = 40;    /* cut size                     */
  51. static int xi, yi;        /* lower-left corner            */
  52. static int bcolor = 1;        /* rubber band color            */
  53. static int overwrite = 1;    /* operation mode. O_MASK other */
  54. static int cp_preview;
  55. static int cp_readscr;
  56. static IPTR cim;
  57. static cpbuf_t cbuf;        /* current cut buffer */
  58.  
  59. /************************************************************
  60.  * A new cut buffer is availble, save it
  61.  *************************************************************/
  62. static void
  63. set_cut_buf(cpbuf_t * buf, int h, int w, void *mat)
  64. {
  65.     if (!mat || !buf)
  66.     return;
  67.     free_mat(buf->buf);
  68.     buf->buf = mat;
  69.     buf->rasbuf = ((char **) mat)[0];
  70.     buf->w = w;
  71.     buf->h = h;
  72.     empty = 0;
  73. }
  74.  
  75. /*****************************************************************
  76.  * Release all memory used by cut buffer buf
  77.  ****************************************************************/
  78. static void
  79. remove_cut_buf(cpbuf_t * buf)
  80. {
  81.     if (buf)
  82.       {
  83.       free_mat(buf->buf);
  84.       buf->buf = 0;
  85.       buf->w = buf->h = 0;
  86.       empty = 1;
  87.       }
  88. }
  89.  
  90. /***************************************************************
  91.  * Undo: for both c&p and scp
  92.  **************************************************************/
  93.  
  94. static int lpxi, lpyi, lpw, lph;/* last pasted position */
  95. static void **undobuf;        /* the undo buffer */
  96.  
  97. static void
  98. cp_undo(IPTR im)
  99. {
  100.     long owin = winget();
  101.  
  102.     if (lpw > 0 && lph > 0 && undobuf)
  103.       {
  104.       set_current_window(win_id);
  105.       Rectwrite(lpxi, lpyi, lpxi + lpw - 1, lpyi + lph - 1, undobuf[0]);
  106.       put_subimage(im, undobuf, make_rect(lpxi, lpyi, lpw, lph), 1);
  107.       lpw = lph = 0;
  108.       free_mat(undobuf);
  109.       undobuf = 0;
  110.       set_current_window(owin);
  111.       }
  112. }
  113.  
  114. /**************** local and GUI functions ****************/
  115.  
  116. static int cp_init(IPTR, int);    /* initialization       */
  117. static void cp_cut(IPTR);    /* cut                   */
  118. static void cp_paste(IPTR);    /* paste                 */
  119. static int cp_keybd(IPTR, int);    /* keyboard input handler */
  120. static void cp_undo(IPTR);
  121. static void cp_move(IPTR);
  122. static void cp_no_buf(IPTR);
  123.  
  124. static void re_size_region(int *, int *, int *, int *, int);
  125. static void create_form_cp(void);
  126.  
  127. static FL_FORM *cp;
  128. static FL_OBJECT *br, *bufname;
  129.  
  130. /************************************************************
  131.  * The global entry point
  132.  ************************************************************/
  133. int
  134. do_cut_paste(IPTR im)
  135. {
  136.     short val;
  137.     int lw = wd, lh = ht, cpdone = 0;
  138.     long dev;
  139.  
  140.     if (cp_init(im, 0) < 0)
  141.     return -1;
  142.  
  143.     set_rubber_obj(RB_RECT);
  144.  
  145.     /* how to handle window manager re-position/resize events */
  146.     install_wm_handler(cp_init);
  147.  
  148.     cim = im;
  149.     empty = 1;
  150.  
  151.     create_form_cp();
  152.     bit_show_form(cp, FL_PLACE_MOUSE, 0, "Cut & Paste");
  153.  
  154.     do
  155.       {
  156.       set_cursor(win_id, empty ? CUR_DEFAULT : CUR_S_FRECT);
  157.       dev = rubber_cursor(win_id, &val, &xi, &yi, wd, ht,
  158.                   (show_cut_buffer && !empty) ? 0 : bcolor);
  159.       cp_move(im);
  160.  
  161.       switch (bit_handle_event(dev, val))
  162.         {
  163.         case MIDDLEMOUSE:
  164.         if (val)
  165.             cp_paste(im);
  166.         break;
  167.         case LEFTMOUSE:
  168.         if (val)
  169.             cp_cut(im);
  170.         break;
  171.         case MENUBUTTON:
  172.         if (val)
  173.           {
  174.               reset_cursor(win_id);
  175.               re_size_region(&xi, &yi, &wd, &ht, bcolor);
  176.               if (lw != wd || lh != ht)
  177.             {
  178.                 cp_no_buf(im);
  179.                 lw = wd;
  180.                 lh = ht;
  181.             }
  182.           }
  183.         break;
  184.         case UPARROWKEY:
  185.         if (val)
  186.             cp_keybd(im, 'k');
  187.         break;
  188.         case DOWNARROWKEY:
  189.         if (val)
  190.             cp_keybd(im, 'j');
  191.         break;
  192.         case LEFTARROWKEY:
  193.         if (val)
  194.             cp_keybd(im, 'h');
  195.         break;
  196.         case RIGHTARROWKEY:
  197.         if (val)
  198.             cp_keybd(im, 'l');
  199.         break;
  200.         case KEYBD:
  201.         cpdone = cpdone || cp_keybd(im, val);
  202.         break;
  203.  
  204.         }
  205.       }
  206.     while (!cpdone);
  207.  
  208.     /* clean up */
  209.     bit_hide_form(cp);
  210.     remove_wm_handler(cp_init);
  211.     set_current_window(win_id);
  212.     rubber_finish();
  213.     cp_no_buf(im);
  214.  
  215.     /*
  216.      * need to reset to none. other routines might need to use sub_mat
  217.      * routine
  218.      */
  219.     set_mat_op(O_NONE);
  220.     return 0;
  221. }
  222.  
  223. /***********************************************************
  224.  * set the region that is c&p'able, taking into account
  225.  * options: if operation is not overwrite, regions outside
  226.  * the image is NOT c&p'able
  227.  **********************************************************/
  228.  
  229. static void
  230. set_bounds(IPTR ip)
  231. {
  232.     int xb1 = Min(ip->xi, 0), xb2 = Max(ip->xf, win_w);
  233.     int yb1 = Min(ip->yi, 0), yb2 = Max(ip->yf, win_h);
  234.  
  235.     if (cp_preview && cp_readscr && overwrite == 1)
  236.     set_rubber_bounds(1, xb1, yb1, xb2, yb2);
  237.     else
  238.     set_rubber_bounds(1, ip->xi, ip->yi, ip->w, ip->h);
  239. }
  240.  
  241. /************************************************************
  242.  * Set initial size.
  243.  ********************************************************/
  244.  
  245. /*ARGSUSED*/
  246. static int
  247. cp_init(IPTR ip, int wme)
  248. {
  249.     set_current_window(win_id);
  250.     rectzoom(1.0, 1.0);
  251.     xi = ip->xi + (ip->w - wd) / 2;
  252.     yi = ip->yi + (ip->h - ht) / 2;
  253.     set_rubber_center(0);
  254.     set_mat_op(overwrite ? O_NONE : O_MASK);
  255.     set_bounds(ip);
  256.     return 0;
  257. }
  258.  
  259. /********************************************************
  260.  * for precise placement, keyboard is better. Also if ESC
  261.  * is pressed, return 1 to signify  done
  262.  ********************************************************/
  263. static int
  264. cp_keybd(IPTR im, int val)
  265. {
  266.     int quit = 0;
  267.     int oh = ht, ow = wd;
  268.     static int step = 1;
  269.  
  270.     switch (val)
  271.       {
  272.       case 27:            /* esc: */
  273.       quit = 1;
  274.       break;
  275.       case 'c':
  276.       case 'C':        /* cut */
  277.       cp_cut(im);
  278.       break;
  279.       case 'p':
  280.       case 'P':        /* paste */
  281.       cp_paste(im);
  282.       break;
  283.       case 'u':
  284.       case 'U':
  285.       cp_undo(im);
  286.       break;
  287.       case 'x':
  288.       wd -= step;
  289.       break;
  290.       case 'X':
  291.       wd += step;
  292.       break;
  293.       case 'y':
  294.       ht -= step;
  295.       break;
  296.       case 'Y':
  297.       ht += step;
  298.       break;
  299.       case 'h':
  300.       case 'l':
  301.       case 'j':
  302.       case 'k':
  303.       if (val == 'h')
  304.           xi -= step;
  305.       if (val == 'l')
  306.           xi += step;
  307.       if (val == 'j')
  308.           yi -= step;
  309.       if (val == 'k')
  310.           yi += step;
  311.  
  312.       set_mouse(xi + win_xo, yi + win_yo);
  313.       break;
  314.       default:
  315.       if (val > '0' && val <= '9')
  316.           step = val - '0';
  317.       break;
  318.       }
  319.  
  320.     /* if size changes, invalidate the cut buffer */
  321.     if (!(oh == ht && ow == wd))
  322.     cp_no_buf(im);
  323.  
  324.     /* do a final check to make rubber within bounds */
  325.     rubber_moveto(&xi, &yi, &wd, &ht);
  326.     return quit;
  327. }
  328.  
  329. /********************************************************
  330.  * import an external image as a cut buffer.
  331.  ********************************************************/
  332. static void
  333. cp_import(const char *fname)
  334. {
  335.     IPTR im;
  336.     int oreport = report_level;
  337.  
  338.     report_level = -1;        /* suppress reporting */
  339.  
  340.     show_busy("Importing ...");
  341.     if ((im = load_image(fname)))
  342.       {
  343.       /* need to convert both to CPACK */
  344.       if (!IS_CPACK(cim))
  345.         {
  346.         img_convert_type(cim, T_RGBA);
  347.         cim->io->display(cim, 0, 0);
  348.         }
  349.       img_convert_type(im, T_RGBA);
  350.       set_cut_buf(&cbuf, ht = im->h, wd = im->w, im->mraster);
  351.       fl_set_object_label(bufname, "Imported");
  352.       im->mraster = im->raster = 0;
  353.       if (im->type != cim->type)    /* only if rgb & graq */
  354.           cim->type = T_RGBA;
  355.       }
  356.     free_image(im);
  357.     report_level = oreport;
  358.     end_busy();
  359. }
  360.  
  361. static void
  362. cp_move(IPTR im)
  363. {
  364.     static int lxi, lyi;
  365.  
  366.     if (show_cut_buffer && !empty)
  367.       {
  368.       if (double_buf)
  369.         {
  370.         PI_rectwrite(xi, yi, xi + wd - 1, yi + ht - 1, cbuf.rasbuf);
  371.         swapbuffers();
  372.         img_rect_redraw(im, lxi, lyi, wd, ht);
  373.         }
  374.       else
  375.         {
  376.         sim_dbl_swap(im, wd, ht, cbuf.buf, xi, yi, lxi, lyi, O_NONE);
  377.         }
  378.       lxi = xi;
  379.       lyi = yi;
  380.       }
  381. }
  382.  
  383. /********************************************************
  384.  * Change C&P size. Block until a unknown key in entered
  385.  *******************************************************/
  386. static void
  387. re_size_region(int *x, int *y, int *w, int *h, int col)
  388. {
  389.     long dev;
  390.     short val;
  391.  
  392.     do
  393.       {
  394.       dev = rubber_info(win_id, &val, x, y, w, h, col, 15);
  395.       }
  396.     while (handle_const_q(dev, val) == 0);
  397.  
  398.     rubber_finish();
  399. }
  400.  
  401.  
  402. static int ncpbuf;
  403. int
  404. no_of_cut_paste_buffers(void)
  405. {
  406.  
  407.     return (!cp || (ncpbuf = fl_get_browser_maxline(br)) <= 0) ?
  408.     0 : ncpbuf;
  409. }
  410.  
  411. const char *
  412. cut_paste_buffer_name(int i)
  413. {
  414.     int j = i + 1;
  415.     return (j < 1 || j > ncpbuf) ? 0 :
  416.     fl_get_browser_line(br, j);
  417. }
  418.  
  419.  
  420. static void
  421. stop_at_first_space(char name[])
  422. {
  423.     char *p = strchr(name, ' ');
  424.     if (p)
  425.     *p = '\0';
  426. }
  427.  
  428. /****************************************************************
  429.  * remove all buffers. Global cleanup
  430.  *****************************************************************/
  431. void
  432. cleanup_cut_paste(void)
  433. {
  434.     int i, imax;
  435.     char name[1024];
  436.  
  437.     if (!cp || (imax = fl_get_browser_maxline(br)) <= 0)
  438.     return;
  439.  
  440.     fl_freeze_form(cp);
  441.     for (i = 1; i <= imax; i++)
  442.       {
  443.       strcpy(name, fl_get_browser_line(br, i));
  444.       stop_at_first_space(name);
  445.       (void) remove(get_TMPfile(name));
  446.       }
  447.     fl_clear_browser(br);
  448.     fl_unfreeze_form(cp);
  449.  
  450.     ncpbuf = 0;
  451. }
  452.  
  453.  
  454. /*******************************************************
  455.  * save the current region and put the cut into un-named
  456.  * buffer
  457.  ********************************************************/
  458. static void
  459. cp_cut(IPTR im)
  460. {
  461.     if (wd == 0 || ht == 0)
  462.     return;
  463.  
  464.     show_busy("");
  465.     set_current_window(win_id);
  466.  
  467.     if (cp_readscr)
  468.       {
  469.       set_cut_buf(&cbuf, ht, wd, get_mat(ht, wd, im->esize));
  470.       Rectread(xi, yi, xi + wd - 1, yi + ht - 1, cbuf.rasbuf);
  471.       }
  472.     else
  473.       {
  474.       set_cut_buf(&cbuf, ht, wd, get_subimage(im, xi, yi, wd, ht));
  475.       }
  476.     fl_set_object_label(bufname, "unnamed");
  477.     end_busy();
  478. }
  479.  
  480. /***************************************************************
  481.  * paste the cut buffer. If commit flag is on, change the raster
  482.  * as well
  483.  ***************************************************************/
  484. static void
  485. cp_paste(IPTR im)
  486. {
  487.     int lx = 0, ly = 0;
  488.  
  489.     if (empty)
  490.     return;
  491.  
  492.     rubber_hide();
  493.     set_current_window(win_id);
  494.  
  495.     if (cbuf.h != ht || cbuf.w != wd)
  496.       {
  497.       M_err("Paste", "something is wrong ");
  498.       return;
  499.       }
  500.  
  501.     do
  502.       {
  503.       get_mouse_r2w(&xi, &yi);
  504.       rubber_moveto(&xi, &yi, &wd, &ht);    /* checking position */
  505.       if (lx != xi || ly != yi)
  506.         {
  507.         /* save for possible undo */
  508.         lpw = wd;
  509.         lph = ht;
  510.  
  511.         undobuf = no_fail_get_subimage(im, xi, yi, wd, ht);
  512.  
  513.         if (!cp_preview)
  514.           {
  515.               put_subimage(im, cbuf.buf, make_rect(xi, yi, wd, ht), 1);
  516.           }
  517.  
  518.         /*
  519.          * can't simply use Rectwrite, because of possibility of
  520.          * Masking option. Write from the image
  521.          */
  522.         dbl_rect_redraw(im, xi, yi, wd, ht);
  523.  
  524.         lx = lpxi = xi;
  525.         ly = lpyi = yi;
  526.         }
  527.       }
  528.     while (getbutton(MIDDLEMOUSE));
  529. }
  530.  
  531. /*******************************************************
  532.  * A name for buffer is entered, save it so
  533.  *****************************************************/
  534. /* ARGSUSED */
  535. static void
  536. save_buf(FL_OBJECT * ob, long l)
  537. {
  538.     rgba_t *tmp, *tend;
  539.     ci_t *ci;
  540.     CMPTR m = cim->cmap;
  541.     FILE *fp;
  542.     char line[50], size[50], *p;
  543.     int i, imax = fl_get_browser_maxline(br), k = -1;
  544.     long total = cbuf.w * cbuf.h;
  545.     const char *pp;
  546.  
  547.     if (empty || !(pp = getstring("Buffername", "", 1)) || !*pp)
  548.     return;
  549.  
  550.     Strncpy(line, pp, sizeof(line));
  551.  
  552.     /* remove all spaces */
  553.     i = 0;
  554.     while (line[i])
  555.       {
  556.       if (line[i] == ' ')
  557.           line[i] = '_';
  558.       i++;
  559.       }
  560.  
  561.     for (i = 1; i <= imax && k < 0; i++)
  562.       {
  563.       Strncpy(size, fl_get_browser_line(br, i), sizeof(size));
  564.       if ((p = strchr(size, ' ')))
  565.           *p = 0;
  566.       if (strcmp(line, size) == 0)
  567.         {
  568.         k = i;
  569.         }
  570.       }
  571.  
  572.     if (k > 0)
  573.       {
  574.       if (!yes_no("Warning",
  575.          "Buffer by the same name already exits", "Overwrite ?", 0))
  576.           return;
  577.       }
  578.     show_busy("SaveCutBuf ...");
  579.     if (IS_CI(cim))
  580.       {
  581.       tmp = malloc(sizeof(rgba_t) * total);
  582.       ci = cbuf.rasbuf;
  583.       for (tend = tmp + total; tmp < tend; tmp++, ci++)
  584.         {
  585.         *ci &= PCMAXV;
  586.         *tmp = Pack(m->ct[0][*ci], m->ct[1][*ci], m->ct[2][*ci]);
  587.         }
  588.       tmp = tend - total;
  589.       }
  590.     else
  591.       {
  592.       tmp = cbuf.rasbuf;
  593.       }
  594.  
  595.     if (!(fp = get_TMPfile_fp(line, "w")))
  596.     return;
  597.  
  598.     put2LSBF(cbuf.w, fp);
  599.     put2LSBF(cbuf.h, fp);
  600.     if (Badfwrite(tmp, sizeof(rgba_t), total, fp))
  601.       {
  602.       Bark("SaveBuf", "Bad Write");
  603.       }
  604.     fclose(fp);
  605.     sprintf(size, " (%dX%d)", cbuf.w, cbuf.h);
  606.     strncat(line, size, sizeof(line) - 1);
  607.  
  608.     if (k < 0)
  609.     fl_add_browser_line(br, line);
  610.     else
  611.     fl_replace_browser_line(br, k, line);
  612.  
  613.     if (tmp != cbuf.rasbuf)
  614.     free(tmp);
  615.     end_busy();
  616. }
  617.  
  618. /*************************************************************************
  619.  * a named buffer is selected
  620.  *************************************************************************/
  621. /* ARGSUSED */
  622. static void
  623. load_buf(FL_OBJECT * ob, long l)
  624. {
  625.     int i;
  626.     char name[120];
  627.     FILE *fp;
  628.     long total;
  629.  
  630.     if ((i = fl_get_browser(br)) <= 0)
  631.     return;
  632.  
  633.     Strncpy(name, fl_get_browser_line(br, i), sizeof(name));
  634.     stop_at_first_space(name);
  635.  
  636.     /* read from disk */
  637.     if (!(fp = get_TMPfile_fp(name, "r")))
  638.     return;
  639.  
  640.     cbuf.w = get2LSBF(fp);
  641.     cbuf.h = get2LSBF(fp);
  642.     if ((total = cbuf.w * cbuf.h) <= 0)
  643.       {
  644.       Bark("ReadBuf", "%s: Bad size w=%d h=%d", name, wd, ht);
  645.       empty = 1;
  646.       return;
  647.       }
  648.  
  649.     empty = 0;
  650.     show_busy("LoadCutBuf ...");
  651.     free_mat(cbuf.buf);
  652.     cbuf.buf = 0;
  653.     cbuf.buf = get_mat(cbuf.h, cbuf.w, sizeof(rgba_t));
  654.     cbuf.rasbuf = ((rgba_t **) cbuf.buf)[0];
  655.  
  656.     if (Badfread(cbuf.rasbuf, sizeof(rgba_t), total, fp))
  657.       {
  658.       Bark("ReadBuf", "%s: Bad read", name);
  659.       empty = 1;
  660.       }
  661.     fclose(fp);
  662.  
  663.     /* need to convert the image to RGB if it's not already */
  664.     wd = cbuf.w;
  665.     ht = cbuf.h;
  666.     if (!empty)
  667.       {
  668.       fl_set_object_label(bufname, name);
  669.       if (!IS_CPACK(cim))
  670.         {
  671.         show_busy("Converting to RGB ...");
  672.         img_convert_type(cim, T_RGBA);
  673.         cim->io->display(cim, 0, 0);    /* display will reset cursor */
  674.         }
  675.       }
  676.     end_busy();
  677. }
  678.  
  679. /* ARGSUSED */
  680. static void
  681. import_cb(FL_OBJECT * ob, long q)
  682. {
  683.     const char *imfile;
  684.     if ((imfile = getfilename("ImportFile", ".", "*.*", "", 1)))
  685.     cp_import(imfile);
  686. }
  687.  
  688. /* ARGSUSED */
  689. static void
  690. del_buf(FL_OBJECT * ob, long l)
  691. {
  692.     int i = fl_get_browser(br);
  693.     char line[50], *p;
  694.  
  695.     if (i <= 0)
  696.     return;
  697.     Strncpy(line, fl_get_browser_line(br, i), sizeof(line));
  698.     if ((p = strchr(line, ' ')))
  699.     *p = '\0';
  700.     (void) remove(get_TMPfile(line));
  701.     fl_delete_browser_line(br, i);
  702. }
  703.  
  704. /* ARGSUSED */
  705. static void
  706. del_all_buf(FL_OBJECT * ob, long l)
  707. {
  708.     cleanup_cut_paste();
  709. }
  710.  
  711. /* ARGSUSED */
  712. static void
  713. finish_cp(FL_OBJECT * obj, long l)
  714. {
  715.     set_mat_op(O_NONE);
  716.     fl_qenter(KEYBD, 27);
  717.  
  718. }
  719.  
  720. /* ARGSUSED */
  721. static void
  722. set_cut_source(FL_OBJECT * ob, long q)
  723. {
  724.     cp_readscr = fl_get_choice(ob) == 1;
  725.     set_bounds(cim);
  726. }
  727.  
  728. /* ARGSUSED */
  729. static void
  730. set_cp_mode(FL_OBJECT * ob, long l)
  731. {
  732.     overwrite = fl_get_choice(ob) == 1;
  733.     set_bounds(cim);
  734.     set_mat_op(overwrite ? O_NONE : O_MASK);
  735. }
  736.  
  737. /*ARGSUSED */
  738. static void
  739. set_cp_op(FL_OBJECT * ob, long q)
  740. {
  741.     cp_preview = fl_get_choice(ob) == 1;
  742.     set_bounds(cim);
  743. }
  744.  
  745. /* Short cuts to carry out control panel requests */
  746. typedef struct
  747. {
  748.     const char *name;
  749.     void (*cb) (FL_OBJECT *, long);
  750.     int bcolor;
  751. }
  752. cbbuf_;
  753.  
  754. /* ARGSUSED */
  755. static void
  756. undo_paste(FL_OBJECT * ob, long q)
  757. {
  758.     cp_undo(imgptr);
  759. }
  760.  
  761. static cbbuf_ cbbuf[] =
  762. {
  763.     {"Import", import_cb, FL_GREEN},
  764.     {"Save", save_buf, FL_GREEN},
  765.     {"Undo", undo_paste, FL_GREEN},
  766.     {"Delete", del_buf, FL_YELLOW},
  767.     {"DelAll", del_all_buf, FL_RED},
  768.     {0, 0, 0}
  769. };
  770.  
  771. /********************************************************************
  772.  * Remove last buffer
  773.  *******************************************************************/
  774. static void
  775. cp_no_buf(IPTR im)
  776. {
  777.     if (!empty)
  778.       {
  779.       if (show_cut_buffer)
  780.         {
  781. #ifndef SGL_BUF
  782.         if (double_buf)
  783.             swapbuffers();
  784. #endif
  785.         img_rect_redraw(im, xi, yi, wd, ht);
  786.         }
  787.       reset_cursor(win_id);
  788.       remove_cut_buf(&cbuf);
  789.       }
  790. }
  791.  
  792. static void
  793. create_form_cp(void)
  794. {
  795.     FL_OBJECT *obj;
  796.     static int ok;
  797.     float x, y, dx, dy;
  798.     cbbuf_ *aa = cbbuf;
  799.  
  800.     if (ok)
  801.     return;
  802.     cp = fl_bgn_form(FL_NO_BOX, 260.0, 280.0);
  803.     obj = fl_add_box(FL_UP_BOX, 0.0, 0.0, 260.0, 280.0, "");
  804.     fl_set_object_color(obj, 9, 47);
  805.     obj = fl_add_button(FL_HB, 0, 0, 260, 280, "");
  806.     fl_set_call_back(obj, help_cb, HELP_CP);
  807.  
  808.     br = obj = fl_add_browser(FL_HBR, 10.0, 15.0, 150.0, 205.0, "");
  809.     fl_set_object_boxtype(obj, FL_SHADOW_BOX);
  810.     fl_set_object_color(obj, 9, 3);
  811.     fl_set_browser_fontsize(obj, 10.0);
  812.     fl_set_call_back(obj, load_buf, 0);
  813.  
  814.     bufname = obj = fl_add_text(FL_NT, 170.0, 195.0, 80.0, 25.0, "");
  815.     fl_set_object_boxtype(obj, FL_BORDER_BOX);
  816.     fl_set_object_lsize(obj, 10.0);
  817.     fl_set_object_align(obj, FL_ALIGN_CENTER);
  818.     fl_set_object_label(obj, "None");
  819.  
  820.     x = 170.0;
  821.     y = 160.0;
  822.     dx = 80.0;
  823.     dy = 25.0;
  824.     while (aa && aa->name)
  825.       {
  826.       obj = fl_add_button(FL_NB, x, y, dx, dy, aa->name);
  827.       fl_set_object_lsize(obj, 10.0);
  828.       fl_set_object_color(obj, FL_MAGIC1, aa->bcolor);
  829.       fl_set_call_back(obj, aa->cb, 0);
  830.       aa++;
  831.       y -= dy;
  832.       }
  833.  
  834.     y = 10;
  835.     obj = fl_add_button(FL_NB, x, y, dx, dy, "Done");
  836.     fl_set_object_lsize(obj, 10.0);
  837.     fl_set_call_back(obj, finish_cp, 0);
  838.  
  839. /* options */
  840.     obj = fl_add_choice(FL_NC, 10.0, 240.0, 80.0, 25.0, "");
  841.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  842.     fl_set_choice_fontstyle(obj, FL_BOLD_STYLE);
  843.     fl_set_choice_fontsize(obj, 10.0);
  844.     fl_addto_choice(obj, "Preview");
  845.     fl_addto_choice(obj, "Commit");
  846.     fl_set_choice(obj, cp_preview ? 1 : 2);
  847.     fl_set_call_back(obj, set_cp_op, 0);
  848.  
  849.     obj = fl_add_choice(FL_NORMAL_CHOICE, 170.0, 240.0, 80.0, 25.0, "");
  850.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  851.     fl_set_choice_fontstyle(obj, FL_BOLD_STYLE);
  852.     fl_set_choice_fontsize(obj, 10.0);
  853.     fl_addto_choice(obj, "Overwrite");
  854.     fl_addto_choice(obj, "Mask");
  855.     fl_set_choice(obj, overwrite ? 1 : 2);
  856.     fl_set_call_back(obj, set_cp_mode, 0);
  857.  
  858.     obj = fl_add_choice(FL_NORMAL_CHOICE, 90.0, 240.0, 80.0, 25.0, "");
  859.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  860.     fl_set_choice_fontstyle(obj, FL_BOLD_STYLE);
  861.     fl_set_choice_fontsize(obj, 10.0);
  862.     fl_addto_choice(obj, "ReadScr");
  863.     fl_addto_choice(obj, "Internal");
  864.     fl_set_choice(obj, cp_readscr ? 1 : 2);
  865.     fl_set_call_back(obj, set_cut_source, 0);
  866.     ok = 1;
  867.     fl_end_form();
  868. }
  869.